package com.example.agent;

import java.lang.instrument.Instrumentation;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.matcher.ElementMatchers;
import org.itstack.demo.agent.MyListener;

/**
 * 博客：http://itstack.org
 * 论坛：http://bugstack.cn
 * 公众号：bugstack虫洞栈  ｛获取学习源码｝
 */
public class MyAgent {

    /**
     * v1.0
     * 如果此方法存在，则优先调用
     * JVM 首先尝试在代理类上调用以下方法
     *
     * @param agentArgs 参数
     */
    // public static void premain(String agentArgs, Instrumentation inst) {
    //     System.out.println("嗨！JavaAgent " + agentArgs);
    // }

    // v1.1
    // public static void premain(String agentArgs, Instrumentation inst) {
    //     System.out.println("this is my agent：" + agentArgs);
    //     MyMonitorTransformer monitor = new MyMonitorTransformer();
    //     inst.addTransformer(monitor);
    // }

    // v1.2
    // public static void premain(String agentArgs, Instrumentation inst) {
    //     System.out.println("this is my agent：" + agentArgs);
    //
    //     AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() {
    //         @Override
    //         public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder
    //                 , TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule) {
    //             return builder
    //                     .method(ElementMatchers.any()) // 拦截任意方法
    //                     .intercept(MethodDelegation.to(MethodCostTime.class)); // 委托
    //         }
    //     };
    //
    //     new AgentBuilder
    //             .Default()
    //             // 指定需要拦截的类
    //             .type(ElementMatchers.nameStartsWith("org.itstack.demo.test"))
    //             .transform(transformer)
    //             .with(new MyListener())
    //             .installOn(inst);
    // }

    // v1.3
    // public static void premain(String agentArgs, Instrumentation inst) {
    //     System.out.println("this is my agent：" + agentArgs);
    //
    //     Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
    //         public void run() {
    //             JvmStack.printMemoryInfo();
    //             JvmStack.printGCInfo();
    //             System.out.println("===================================================================================================");
    //         }
    //     }, 0, 5000, TimeUnit.MILLISECONDS);
    // }

    // v1.4
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("基于javaagent链路追踪");

        AgentBuilder agentBuilder = new AgentBuilder.Default();

        AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, javaModule) -> {
            builder = builder.visit(
                    Advice.to(MyAdvice.class)
                            .on(ElementMatchers.isMethod()
                                    .and(ElementMatchers.any()).and(ElementMatchers.not(ElementMatchers.nameStartsWith("main")))));
            return builder;
        };

        agentBuilder = agentBuilder.type(ElementMatchers.nameStartsWith("org.itstack.demo.test"))
                .transform(transformer);

        //监听
        agentBuilder.with(new MyListener()).installOn(inst);

    }

    /**
     * 如果代理类没有实现上面的方法，那么 JVM 将尝试调用该方法
     *
     * @param agentArgs 参数
     */
    public static void premain(String agentArgs) {
    }

}
